#include "devinsight.h"
#include "utils/builtins.h"
#include "nodes/parsenodes.h"
#include "tcop/tcopprot.h"


static const char* _dvi_optimizer_tree(const char* sql, int step)
{
    /* 这是个函数，执行时早就启动过事务、获取过快照之类的了，所以这里直接调接口就行。 */

    /* 语法分析树 */
    List* parsetree_list = pg_parse_query(sql);
    if (step == 1) {
        return nodeToString(parsetree_list);
    }

    /* 逻辑查询树 */
    if (list_length(parsetree_list) != 1) {
        return "暂时不支持多条SQL获取Query tree。";
    }
    List* querytree_list = pg_analyze_and_rewrite((Node*)lfirst(list_head(parsetree_list)), sql, NULL, 0);
    if (step == 2) {
        return nodeToString(querytree_list);
    }


    /* 查询计划树 */
    List* plantree_list = pg_plan_queries(querytree_list, CURSOR_OPT_SPQ_OK, NULL);
    return nodeToString(plantree_list);
}



PG_FUNCTION_INFO_V1(dvi_parsetree);
extern "C" Datum dvi_parsetree(PG_FUNCTION_ARGS);
Datum dvi_parsetree(PG_FUNCTION_ARGS)
{
    char* sql = TextDatumGetCString(PG_GETARG_TEXT_P(0));

    PG_RETURN_CSTRING(_dvi_optimizer_tree(sql, 1));
}

PG_FUNCTION_INFO_V1(dvi_querytree);
extern "C" Datum dvi_querytree(PG_FUNCTION_ARGS);
Datum dvi_querytree(PG_FUNCTION_ARGS)
{
    char* sql = TextDatumGetCString(PG_GETARG_TEXT_P(0));

    PG_RETURN_CSTRING(_dvi_optimizer_tree(sql, 2));
}

PG_FUNCTION_INFO_V1(dvi_plantree);
extern "C" Datum dvi_plantree(PG_FUNCTION_ARGS);
Datum dvi_plantree(PG_FUNCTION_ARGS)
{
    char* sql = TextDatumGetCString(PG_GETARG_TEXT_P(0));

    PG_RETURN_CSTRING(_dvi_optimizer_tree(sql, 3));
}


PG_FUNCTION_INFO_V1(dvi_parsetree_copyobject);
extern "C" Datum dvi_parsetree_copyobject(PG_FUNCTION_ARGS);
Datum dvi_parsetree_copyobject(PG_FUNCTION_ARGS)
{
    char* sql = TextDatumGetCString(PG_GETARG_TEXT_P(0));

    List* parsetree_list = pg_parse_query(sql);
    copyObject(parsetree_list);


    PG_RETURN_CSTRING("ok");
}

